<template>
	<el-card class="box-card el-card-flex">
		<div slot="header" class="clearfix">
			<span>
				<i class="el-icon-medal"></i>
				角色授权功能
			</span>
			<div style="float: right;">
				<el-input clearable v-model="fuzzyfield" placeholder="请搜索..." suffix-icon="el-icon-search" style="float:left;width:240px;margin-right: 10px;">
				</el-input>
				<el-checkbox label="仅显示已选中" border v-model="nodeChecked"></el-checkbox>
			</div>

		</div>
		<div class="text item el-over-auto">
			<el-form :model="roleForm" ref="roleForm">
				<el-form-item v-show="nodeIsShow(list)" v-for="(list, index) in funcList" :key="list.id">
					<el-checkbox :label="list.id" v-model="list.checked" :indeterminate="nodeIndeterminate(list)" @change="funCheckChange(list)">{{ list.name }}</el-checkbox>
					<ul class="checkbox-ul">
						<li v-show="nodeIsShow(list2)" class="checkbox-li" v-for="(list2, index2) in list.children" :key="list2.id">
							<div class="checkbox-head">
								<el-checkbox :label="list2.id" v-model="list2.checked" @change="funCheckChange(list2,list)">{{ list2.name }}</el-checkbox>
							</div>
							<div v-show="nodeIsShow(list3)" v-for="(list3, index3) in list2.children" :key="list3.id">
								<label class="checkbox-label">
									<input type="checkbox" class="checkbox-check" v-model="list3.checked" @change="funCheckChange(list3)" />
									<span>{{ list3.name }}</span>
								</label>
							</div>
						</li>
					</ul>
				</el-form-item>
			</el-form>
		</div>
		<div style="text-align: right;padding: 10px;">
			<el-button type="primary" @click="saveRoleFunAuth">
				确定
				<i class="el-icon-document-checked el-icon--right"></i>
			</el-button>
			<el-button @click="goBack">
				取消
				<i class="el-icon-refresh-left"></i>
			</el-button>
		</div>
	</el-card>
</template>
<script>
	import {
		MessageBox, //弹框提示
		Message, //消息提示
	} from 'element-ui'

	import {
		getNodeTree, //获取功能列表
		putRoleFunAuth, //保存角色和功能的授权
	} from '@/api/authority/roleManage/roleBindFun.js'

	export default {
		data() {
			return {
				fuzzyfield: '', //搜索字符
				nodeChecked: false, //筛选已选中数据
				roleForm: {}, //表单数据模型
				funcList: [], //功能项目数据源
				funcCheckedIds: [], //选中的功能节点id合集
			}
		},
		methods: {
			/**
			 * @method nodeIsShow 节点过滤显示
			 * @param {object} list 节点数据源（包含子节点）
			 */
			nodeIsShow(list) {
				if(!this.nodeChecked && !this.fuzzyfield ) return true
				let isCheck = true//筛选已选中的节点
				let isName = true//筛选名称相符的节点
				let str = JSON.stringify(list) //把数据源转成json字符串，用正则表达式进行匹配
				if (this.nodeChecked) { //如果点选了已选中
					let checkReg = new RegExp('"checked":true')
					isCheck = checkReg.test(str)
				}
				if (this.fuzzyfield) { //如果有搜索字符
					let nameReg = new RegExp('"name":"[^("|,)]*' + this.fuzzyfield) //用正则表达式匹配name字段
					isName = nameReg.test(str) 
				}
				return isCheck && isName
			},
			/**
			 * @method nodeIndeterminate 节点半选状态控制
			 * @param {object} list 节点数据源（包含子节点）
			 */
			nodeIndeterminate(list){
				let indeterminate = false
				let cList = list.children//子集
				if(!cList) return false//如无子集则没有半选状态
				let str = JSON.stringify(cList) //把数据源转成json字符串，用正则表达式进行匹配
				let checks = str.match(/"checked":true/g)//匹配子集有无选中
				if(checks){//如果子集有选中
					let ids = str.match(/"id":/g)
					if(checks.length && checks.length == ids.length){//子集全部选中
						list.checked = true
						indeterminate = false//关闭半选
					}else{//子集未全部选中
						list.checked = false
						indeterminate = true//启用半选
					}
				}else{//如果子集无选中
					list.checked = false
				}
				return indeterminate
			},
			/* 返回上一页 */
			goBack() {
				this.$router.push(this.routerMatch({
					name: 'roleManage'
				}))
			},
			/**
			 * @method renderFuncItems 渲染功能列表项
			 * @param {string} roleId 接收的角色主键
			 */
			renderFuncItems(roleId) {
				getNodeTree(roleId).then(res => {
					if (res.data.code != 10000) return
					this.funcList = res.data.data
				})
			},
			/* 保存功能授权*/
			saveRoleFunAuth() {
				this.funcCheckedIds = [] //清空已选中
				this.getFuncByChecked(this.funcList) //根据是否选中，重数据源中筛选出已选中
				let sendDatas = {
					roleIds: [this.$route.params.roleId], //角色主键
					funIds: this.funcCheckedIds //功能主键合集
				}
				putRoleFunAuth(sendDatas).then(res => {
					if (res.data.code != 10000) return
					Message.success('授权功能成功！')
					setTimeout(() => {
						this.goBack() //返回上一页
					}, 2000)
				})
			},
			/**
			 * @method setfuncByPId 根据parentId设置父元素选中模式
			 * @param {string} parentId 父节点的主键
			 * @param {array} funcList 子节点合集
			 * @param {boolean} checked 是否选中
			 */
			setfuncByPId(parentId, funcList, checked) {
				if (parentId && funcList && funcList.length > 0) {
					for (let i = 0, len = funcList.length; i < len; i++) {
						if (funcList[i].id == parentId) {
							if (checked) funcList[i].checked = checked
							this.setfuncByPId(funcList[i].parentId, this.funcList, checked)
						} else {
							this.setfuncByPId(parentId, funcList[i].children, checked)
						}
					}
				}
			},
			/**
			 * @method funCheckChange checkbox选中事件
			 * @param {object} list 当前点击节点的数据源
			 */
			funCheckChange(list) {
				this.setfuncByPId(list.parentId, this.funcList, list.checked) //设置父元素选中模式
				let children = list.children
				if (children) {
					for (let i = 0, len = children.length; i < len; i++) {
						children[i].checked = list.checked
						this.funCheckChange(children[i], list)
					}
				}
			},
			/**
			 * @method getFuncByChecked 获取所有选中的功能主键
			 * @param {array} funcList 所有功能项数据源
			 */
			getFuncByChecked(funcList) {
				if (funcList && funcList.length > 0) {
					for (let i = 0, len = funcList.length; i < len; i++) {
						if (funcList[i].checked) {
							this.funcCheckedIds.push(funcList[i].id)
						}
						this.getFuncByChecked(funcList[i].children)
					}
				}
			}
		},
		created() {
			this.renderFuncItems(this.$route.params.roleId) //获取功能列表
		}
	}
</script>
<style lang="scss">
	.checkbox-head {
		text-align: right;
		padding-right: 5px;
	}

	.checkbox-li {
		float: left;
		width: 180px;
		height: 88px;
		padding: 0 0 5px 5px;
		margin: 0 10px 10px 0;
		border: 1px solid #dcdfe6;
		border-radius: 4px;
		box-sizing: border-box;
	}

	.checkbox-label {
		float: left;
		margin: 0 5px 5px 0;
		position: relative;
	}

	.checkbox-label>span {
		float: left;
		height: 20px;
		line-height: 20px;
		border: 1px solid #dcdfe6;
		border-radius: 20px;
		padding: 0 8px;
		box-sizing: border-box;
		font-size: 10px;
		background: rgb(245, 245, 245);
		cursor: pointer;
	}

	.checkbox-label:hover span {
		background: rgb(235, 235, 235);
	}

	.checkbox-check {
		position: absolute;
		visibility: hidden;
		opacity: 0;
	}

	.checkbox-label:focus span,
	.checkbox-label .checkbox-check:checked+span {
		color: #409eff;
		background: #ecf5ff;
		border-color: #b3d8ff;
	}

	.el-hide {
		display: none !important;
	}
</style>
